package com.yin.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.security.SignatureException;
import java.util.Optional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import com.yin.entity.TokenInfoEntity;
import com.yin.jpa.TokenJPA;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

/**
*@author LSY
*Time: 2018年12月27日下午4:48:53
*
*
*/
public class JwtInterceptor implements HandlerInterceptor{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws IOException {
		if(request.getRequestURI().equals("/token") || RequestMethod.OPTIONS.toString().equals(request.getMethod())) {
			return true;
		}
		final String authHeader = request.getHeader("X-JWT-Token");
		try {
			if(authHeader == null || authHeader.trim().equals("")) {
				throw new SignatureException("no found X-JWT-Token");
			}
			final Claims claims = Jwts.parser().setSigningKey("LSYv1.0.0")
					.parseClaimsJws(authHeader).getBody();
			Optional<TokenInfoEntity> op = getDao(TokenJPA.class, request).findOne(new Specification<TokenInfoEntity>() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				@Override
				public Predicate toPredicate(Root<TokenInfoEntity> root, CriteriaQuery<?> query,
						CriteriaBuilder criteriaBuilder) {
					query.where(criteriaBuilder.equal(root.get("appId"), claims.getSubject()));
					return null;
				}
			});
			TokenInfoEntity token = op.isPresent()? op.get() : new TokenInfoEntity();
			String tokenVal = new String(token.getToken());
			if(tokenVal == null || tokenVal.trim().equals("")) {
				throw new SignatureException("not found tokenInfo, please get token agin");
			}
			if(!tokenVal.equals(authHeader)) {
				throw new SignatureException("not found tokenInfo, please get token agin");
			}
		} catch (Exception e) {
			PrintWriter writer = response.getWriter();
			writer.write("need refresh token");
			writer.close();
			return false;
		}
		return true;
	}
	
	 @SuppressWarnings("unused")
	private <T> T getDao(Class<T> clazz,HttpServletRequest request) {
	    	BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
	    	return factory.getBean(clazz);
	    }
	
}
